<?php

use Doraemon\pockets\constInterface\ApiCode;
use Doraemon\pockets\encrypt\Xxtea;

class RequestEncryptionPlugin extends Yaf_Request_Http implements ApiCode
{
    const IOS_PRE_KEY = "adpKEq7GVMjHveZqMEt4c3,bF8";

    const ANDROID_PRE_KEY = "qEpcsu2CCkruqxB6h.itrY2p2tx";

    const SECRET_KEY = "ALoU}99gpVV>vWth^HBA32NrW";

    //解密兼容开关，1表示打开，0表示关闭 
    const DECRYPT_SWITCH = 1;

    private $sign2key = array(
        '3vo9' => 'e%qmRlw8Si*ih0P8QHWH*zI124RsGu&&'
    );

    public function getPost($name = null, $default = null)
    {
        $moduleName = parent::getModuleName();
        if ($moduleName != "Index") {
            if (func_num_args()) {
                return parent::getPost($name, $default);
            } else {
                return parent::getPost();
            }
        }
        $params = parent::getPost("shawshank");
        if (!$params) {
            if (self::DECRYPT_SWITCH) {
                if (!$name && !$default) {
                    return parent::getPost();
                }
                return parent::getPost($name, $default);
            }
            throw new \Exception("params decryp failure", self::API_CODE_DECRYPT_EXCEPTION);
        }
        $params = $this->decryptData($params);
        if (!$params) {
            //错误输出
            throw new \Exception("params decryp failure", self::API_CODE_DECRYPT_EXCEPTION);
        }
        $params = $this->paramsDecode($params);
//        foreach ($params as &$val) {
//            $val = urldecode($val);
//        }
        if (!$name && !$default) {
            return $params;
        }
        return isset($params[$name]) ? $params[$name] : $default;
        /*
        if (!isset($params[$name]) && $default){
            return $default;
        }
        if (isset($params[$name]) && $params[$name]) {
            return $params[$name];
        }
         */
    }

    private function paramsDecode($params)
    {
        if (is_array($params)) {
            foreach ($params as &$row) {
                $row = $this->paramsDecode($row);
            }
            return $params;
        } else {
            return urldecode($params);
        }
    }

    public function getQuery($name = null, $default = null)
    {
        $moduleName = parent::getModuleName();
        if ($moduleName == "Inner") {
            return parent::getQuery($name, $default);
        }
        $params = parent::getQuery("shawshank");
        if (!$params) {
            if (self::DECRYPT_SWITCH) {
                if (!$name && !$default) {
                    return parent::getQuery();
                }
                return parent::getQuery($name, $default);
            }
            throw new \Exception("params decryp failure", self::API_CODE_DECRYPT_EXCEPTION);
        }
        $params = $this->decryptData($params);
        if (!$params) {
            //错误输出
            throw new \Exception("params decryp failure", self::API_CODE_DECRYPT_EXCEPTION);
        }
        $params = $this->paramsDecode($params);
//        foreach ($params as &$val) {
//            $val = urldecode($val);
//        }
        if (!$name && !$default) {
            return $params;
        }
        return isset($params[$name]) ? $params[$name] : $default;
    }

    public function get($name = null, $default = null)
    {
        $moduleName = parent::getModuleName();
        if ($moduleName == "Inner") {
            return parent::get($name, $default);
        }
        $params = parent::get("shawshank");
        if (!$params) {
            if (self::DECRYPT_SWITCH) {
                if (!$name && !$default) {
                    return parent::get();
                }
                return parent::get($name, $default);
            }
            throw new \Exception("params decryp failure", self::API_CODE_DECRYPT_EXCEPTION);
        }
        $params = $this->decryptData($params);
        if (!$params) {
            //错误输出
            throw new \Exception("params decryp failure", self::API_CODE_DECRYPT_EXCEPTION);
        }
//        foreach ($params as &$val) {
//            $val = urldecode($val);
//        }
        $params = $this->paramsDecode($params);
        if (!$name && !$default) {
            return $params;
        }
        return isset($params[$name]) ? $params[$name] : $default;
    }

    public function getRequest($name= null, $default = NULL)
    {
        $params = [];
        if (parent::isPost()) {
            $params = parent::getPost("shawshank");
        } else if (parent::isGet()) {
            $params = parent::get("shawshank");
        }
        if (!$params) {
            if (self::DECRYPT_SWITCH) {
                return parent::getRequest();
            }
            throw new \Exception("params decryp failure", self::API_CODE_DECRYPT_EXCEPTION);
        }
        $params = $this->decryptData($params);
        if (!$params) {
            //错误输出
            throw new \Exception("params decryp failure", self::API_CODE_DECRYPT_EXCEPTION);
        }
        $params = $this->paramsDecode($params);
        return $params;
    }

    private function decryptData($data)
    {
        if (preg_match('/\-k[0-9a-z]{4}/', $_SERVER['HTTP_USER_AGENT'], $b) > 0) {

            $sign = substr($b[0], 2);
            if (isset($this->sign2key[$sign])) {
                $key = $this->sign2key[$sign];
            } else {
                return false;
            }
        } else {
            $key = self::SECRET_KEY;
        }


        $ua = $_SERVER['HTTP_USER_AGENT'];
        if (strpos($ua, 'iOS')) {
            $prekey = self::IOS_PRE_KEY;
        } elseif (strpos($ua, 'Android')) {
            $prekey = self::ANDROID_PRE_KEY;
        } else {
            return $data;
        }


        $encryptdata = str_replace($prekey, "", $data);
        $encryptdata = str_replace("_", "/", $encryptdata);
        $encryptdata = str_replace("-", "+", $encryptdata);
        $decodedata = base64_decode($encryptdata);
        $paramstr = XXTEA::decrypt($decodedata, $key);
        $params = json_decode($paramstr, true);
        if (!$params) {
            \Doraemon\tools\Log::api_encrypt_error('encrypted_request', [
                'params_json' => json_encode($params),
                'shawshank' => $data
            ]);
            return false;
        }
        return $params;
    }
}
